const files = require('./../files');
const functions = require('./../functions');
const tests = require('./../tests');
const common = require('./../common');
const userDefinedField = require('../user-defined-fields');
const invokeRelations = require('./../invoke-relations');
const testCaseGroups = require('./../test-case-groups');
const codeDefects = require('../code-defects');
const projectVersions = require('../project-versions');

class BaseDataAdapter {
  async getCompleteVersionInfo(projectId, project = null, creator = null) {
    return common.complementByProjectVersionId(projectId, project, creator);
  }

  async getFiles(versionId) {
    const projectVersion = await projectVersions.getVersion(versionId);
    let suffixes = [];
    Object.keys(projectVersion.languages).forEach((key) => {
      suffixes = suffixes.concat(projectVersion.languages[key].suffixes);
    });
    const extensions = suffixes.concat(projectVersion.headers.suffixes);
    return files.getFiles(versionId, {}, { kinds: files.kind.file, extensions });
  }

  async getIntegratedFilesByTest(testId, testcase = null, funcVariables = null) {
    return tests.getFilesByTestId(testId, testcase, funcVariables);
  }

  async getFunctions(versionId, fileIds = undefined) {
    return functions.getFunctions(versionId, { sort: { fileId: 1 }, collectCoverage: true }, fileIds);
  }

  async getFileTypes(fileId) {
    return files.getTypes(fileId);
  }

  async getFileVariables(fileId, versionId) {
    return functions.getVariablesOfFile(fileId, versionId);
  }

  async getFileTests(fileId) {
    return tests.getTestsOfFile(fileId);
  }

  getTestIdentifier(test) {
    return tests.getTestIdentifier(test);
  }

  async getIntegratedFuncs(functionId, sort = false) {
    return invokeRelations.retrieveRelations(functionId, { sort })
      .then((relations) => {
        const versionId = relations[0] ? relations[0].versionId : null;
        if (!versionId) {
          return [];
        }
        return functions.relationFuncsDeduplicate(relations, versionId);
      })
      .then((relations) => relations.filter((relation) => {
        if (!relation.toFuncId) {
          return false;
        }
        if (relation.enableStub) {
          return false;
        }
        return true;
      }));
  }

  async getIntegratedFuncsVariables(functionId, versionId) {
    if (!this.allFuncVariableStubs) {
      this.allFuncVariableStubs = await functions.getFunctionStubsByVersionId(versionId);
    }
    if (!this.allFileIdsOfVersion) {
      this.allFileIdsOfVersion = await files.getSourceFileByVersionId(versionId, null, { _id: 1, path: 1, fileName: 1 });
    }
    if (!this.allFuncsOfVersion) {
      this.allFuncsOfVersion = await functions.getFunctionByVersionId(versionId, {
        _id: 1, fileId: 1, functionName: 1, functionAttrs: 1, kind: 1,
      });
    }
    return functions.getRelationFuncsVariables(
      functionId,
      {
        allFileMap: this.allFileIdsOfVersion,
        allFuncMap: this.allFuncsOfVersion,
        allFuncVariableStubs: this.allFuncVariableStubs,
      }
    );
  }

  async getUserDefinedFields(versionType) {
    return userDefinedField.listUserDefinedField(versionType);
  }

  async getFileTestCaseGroups(fileId) {
    return testCaseGroups.getGroupByFileId(fileId);
  }

  async getCodeDefects(fileId) {
    return codeDefects.getCodeDefectsByFildId(fileId);
  }

  async getFunctionCfg(func, includeCovered = true) {
    return functions.getFunctionCFG(func._id, null, includeCovered);
  }

  async retrieveRelations(functionId) {
    return invokeRelations.retrieveRelations(functionId);
  }
}

module.exports = BaseDataAdapter;
